DiagrammeR is all about making it easy to create, modify, and analyze graphs in an R environment. When just starting to use the package, it’s useful to learn how to generate and view simple graphs. Here, we’ll use just a few functions to generate node and edge data frames (i.e., graph building blocks), to create the graph object, and to view the graph.
Setup
Ensure that the developement version of DiagrammeR is installed. Load in the package with library() and also ensure that the magrittr package is available.
devtools::install_github("rich-iannone/DiagrammeR")
library(DiagrammeR)
library(magrittr)
Part 1. Creating a Simple Graph Using Data Frames
For graph diagrams you need nodes and edges. Let’s use the create_node_df() function specify a collection of nodes and contain them in a data frame (a node data frame, or ndf). Immediately after that, inspect the node data frame.
ndf <-
create_node_df(
n = 3,
label = TRUE)
ndf
The n argument is required here and it must the number of nodes you intend this object to contain. The use of label = TRUE allows for copying of the node IDs as the node label (which is a node attribute). This is not always desirable, however. A better option is to specify of vector of text labels (you can use all manner of characters), but ensure that this vector is the same length as specified by n. If you ensure that the label node attribute always contains unique values, later on you can select individual nodes by label and perform actions on them.
You may have noticed the node attribute type in the output. Values may optionally be provided for this and they values are useful for categorizing collections of nodes. Let’s refine the ndf object and include two different type values.
ndf <-
create_node_df(
n = 3,
type = c("A", "A", "B"),
label = TRUE)
ndf
Now onto the edges, those connections between the nodes. The edge connections are also collected in a data frame (this time, an edge data frame or edf). The create_edge_df() function is used to generate this object.
edf <-
create_edge_df(
from = c(1, 1),
to = c(2, 3))
edf
The from and to arguments specify which nodes the the edge is outgoing and incoming, respectively. Here, the edges are: “1” -> “2” and “1” -> “3”. For directed graphs, the order is essential. The rel argument allows for inclusion of text labels in the same manner as the node type. This is useful for targeting specific groups of edges during a selection or traversal. Let’s refine the edf object and include two different rel values.
edf <-
create_edge_df(
from = c(1, 1),
to = c(2, 3),
rel = c("X", "Y"))
edf
Now that we have an ndf and an edf, we can now combine those into a graph object.
the_graph <-
create_graph(
nodes_df = ndf,
edges_df = edf)
Having a graph object is a great first step and you can do a lot with them (inspect, modify, join with other graph objects, etc.). Whenever you’d like to view the graph, use the render_graph() function. There are three renderers for graphs:
Graphviz
render_graph(graph = the_graph, output = "graph")
Vivagraph
render_graph(graph = the_graph, output = "vivagraph")
visNetwork
render_graph(graph = the_graph, output = "visNetwork")
Part 2. A Shortcut to the Same Graph
You don’t really need to have a node data frame in conjunction with the edge data frame to make a graph object. You can have both, either of them, or neither of them (creating an empty graph). Here is the empty graph case:
render_graph(create_graph())
If you wanted to make the same non-empty graph as before, but with one less step, just create the edf then use create_graph(). The nodes will have minimal node attributes set (i.e., no type values set).
# Create the edge data frame
edf <-
create_edge_df(
from = c(1, 1),
to = c(2, 3))
# Use the `create_graph()` function
the_graph <- create_graph(edges_df = edf)
# The graph should be similar, but, the node `type`
# hasn't been set (so no coloring of two different
# groups of nodes)
render_graph(graph = the_graph)
Part 3. Graph with Nodes but No Edges
We can just display nodes without edges by passing in just a node data frame to the create_graph() function.
# Create the node data frame
ndf <-
create_node_df(
n = 3,
label = c("A", "B", "C"))
# Use the `create_graph()` function
the_graph <- create_graph(nodes_df = ndf)
# View the graph
render_graph(graph = the_graph)
Here is an example with 26 nodes, this time wrapping the create_nodes(), create_graph(), and render_graph() function calls into one big statement.
render_graph(
create_graph(
nodes_df =
create_node_df(
n = 26,
label = LETTERS)))
Unicode characters can also be used as label attribute values:
render_graph(
create_graph(
nodes_df =
create_node_df(
n = 3,
label = c("α", "β", "γ"))))
Nesting calls like becomes less readable with increasing numbers of operations. DiagrammeR works very well with the magrittr package to allow forward-piping of graph operations with the %>% operator. Here is the same set of functions as above, except using %>% to chain the operations left to right:
create_node_df(
n = 3, label = c("α", "β", "γ")) %>%
create_graph(nodes_df = .) %>%
render_graph
The . character in the create_graph() statement indicates that the returned output from the previous create_node_df() statement should go here. Otherwise, the default behavior is that the output from a statement becomes the value for the first argument (which is often omitted entirely). The functions in DiagrammeR are designed to have this forward-pipe pattern work well. With further examples, you’ll see how this can make even complicated graph operations easy to compose and to read.
LS0tCnRpdGxlOiAiMDAxIC0gQ3JlYXRpbmcgYSBTaW1wbGUgR3JhcGgiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCioqRGlhZ3JhbW1lUioqIGlzIGFsbCBhYm91dCBtYWtpbmcgaXQgZWFzeSB0byBjcmVhdGUsIG1vZGlmeSwgYW5kIGFuYWx5emUgZ3JhcGhzIGluIGFuICoqUioqIGVudmlyb25tZW50LiBXaGVuIGp1c3Qgc3RhcnRpbmcgdG8gdXNlIHRoZSBwYWNrYWdlLCBpdCdzIHVzZWZ1bCB0byBsZWFybiBob3cgdG8gZ2VuZXJhdGUgYW5kIHZpZXcgc2ltcGxlIGdyYXBocy4gSGVyZSwgd2UnbGwgdXNlIGp1c3QgYSBmZXcgZnVuY3Rpb25zIHRvIGdlbmVyYXRlIG5vZGUgYW5kIGVkZ2UgZGF0YSBmcmFtZXMgKGkuZS4sIGdyYXBoIGJ1aWxkaW5nIGJsb2NrcyksIHRvIGNyZWF0ZSB0aGUgZ3JhcGggb2JqZWN0LCBhbmQgdG8gdmlldyB0aGUgZ3JhcGguCgojIyBTZXR1cAoKRW5zdXJlIHRoYXQgdGhlIGRldmVsb3BlbWVudCB2ZXJzaW9uIG9mICoqRGlhZ3JhbW1lUioqIGlzIGluc3RhbGxlZC4gTG9hZCBpbiB0aGUgcGFja2FnZSB3aXRoIGBsaWJyYXJ5KClgIGFuZCBhbHNvIGVuc3VyZSB0aGF0IHRoZSAqKm1hZ3JpdHRyKiogcGFja2FnZSBpcyBhdmFpbGFibGUuCgpgYGB7ciwgcmVzdWx0cz1GQUxTRX0KZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJyaWNoLWlhbm5vbmUvRGlhZ3JhbW1lUiIpCgpsaWJyYXJ5KERpYWdyYW1tZVIpCmxpYnJhcnkobWFncml0dHIpCmBgYAoKIyMgUGFydCAxLiBDcmVhdGluZyBhIFNpbXBsZSBHcmFwaCBVc2luZyBEYXRhIEZyYW1lcwoKRm9yIGdyYXBoIGRpYWdyYW1zIHlvdSBuZWVkIG5vZGVzIGFuZCBlZGdlcy4gTGV0J3MgdXNlIHRoZSBgY3JlYXRlX25vZGVfZGYoKWAgZnVuY3Rpb24gc3BlY2lmeSBhIGNvbGxlY3Rpb24gb2Ygbm9kZXMgYW5kIGNvbnRhaW4gdGhlbSBpbiBhIGRhdGEgZnJhbWUgKGEgbm9kZSBkYXRhIGZyYW1lLCBvciBuZGYpLiBJbW1lZGlhdGVseSBhZnRlciB0aGF0LCBpbnNwZWN0IHRoZSBub2RlIGRhdGEgZnJhbWUuCgpgYGB7cn0KbmRmIDwtIAogIGNyZWF0ZV9ub2RlX2RmKAogICAgbiA9IDMsCiAgICBsYWJlbCA9IFRSVUUpCgpuZGYKYGBgCgpUaGUgYG5gIGFyZ3VtZW50IGlzIHJlcXVpcmVkIGhlcmUgYW5kIGl0IG11c3QgdGhlIG51bWJlciBvZiBub2RlcyB5b3UgaW50ZW5kIHRoaXMgb2JqZWN0IHRvIGNvbnRhaW4uIFRoZSB1c2Ugb2YgYGxhYmVsID0gVFJVRWAgYWxsb3dzIGZvciBjb3B5aW5nIG9mIHRoZSBub2RlIElEcyBhcyB0aGUgbm9kZSBgbGFiZWxgICh3aGljaCBpcyBhIG5vZGUgYXR0cmlidXRlKS4gVGhpcyBpcyBub3QgYWx3YXlzIGRlc2lyYWJsZSwgaG93ZXZlci4gQSBiZXR0ZXIgb3B0aW9uIGlzIHRvIHNwZWNpZnkgb2YgdmVjdG9yIG9mIHRleHQgbGFiZWxzICh5b3UgY2FuIHVzZSBhbGwgbWFubmVyIG9mIGNoYXJhY3RlcnMpLCBidXQgZW5zdXJlIHRoYXQgdGhpcyB2ZWN0b3IgaXMgdGhlIHNhbWUgbGVuZ3RoIGFzIHNwZWNpZmllZCBieSBgbmAuIElmIHlvdSBlbnN1cmUgdGhhdCB0aGUgYGxhYmVsYCBub2RlIGF0dHJpYnV0ZSBhbHdheXMgY29udGFpbnMgdW5pcXVlIHZhbHVlcywgbGF0ZXIgb24geW91IGNhbiBzZWxlY3QgaW5kaXZpZHVhbCBub2RlcyBieSBgbGFiZWxgIGFuZCBwZXJmb3JtIGFjdGlvbnMgb24gdGhlbS4KCllvdSBtYXkgaGF2ZSBub3RpY2VkIHRoZSBub2RlIGF0dHJpYnV0ZSBgdHlwZWAgaW4gdGhlIG91dHB1dC4gVmFsdWVzIG1heSBvcHRpb25hbGx5IGJlIHByb3ZpZGVkIGZvciB0aGlzIGFuZCB0aGV5IHZhbHVlcyBhcmUgdXNlZnVsIGZvciBjYXRlZ29yaXppbmcgY29sbGVjdGlvbnMgb2Ygbm9kZXMuIExldCdzIHJlZmluZSB0aGUgYG5kZmAgb2JqZWN0IGFuZCBpbmNsdWRlIHR3byBkaWZmZXJlbnQgYHR5cGVgIHZhbHVlcy4KCmBgYHtyfQpuZGYgPC0gCiAgY3JlYXRlX25vZGVfZGYoCiAgICBuID0gMywKICAgIHR5cGUgPSBjKCJBIiwgIkEiLCAiQiIpLAogICAgbGFiZWwgPSBUUlVFKQoKbmRmCmBgYAoKTm93IG9udG8gdGhlIGVkZ2VzLCB0aG9zZSBjb25uZWN0aW9ucyBiZXR3ZWVuIHRoZSBub2Rlcy4gVGhlIGVkZ2UgY29ubmVjdGlvbnMgYXJlIGFsc28gY29sbGVjdGVkIGluIGEgZGF0YSBmcmFtZSAodGhpcyB0aW1lLCBhbiBlZGdlIGRhdGEgZnJhbWUgb3IgZWRmKS4gVGhlIGBjcmVhdGVfZWRnZV9kZigpYCBmdW5jdGlvbiBpcyB1c2VkIHRvIGdlbmVyYXRlIHRoaXMgb2JqZWN0LgoKYGBge3J9CmVkZiA8LSAKICBjcmVhdGVfZWRnZV9kZigKICAgIGZyb20gPSBjKDEsIDEpLAogICAgdG8gICA9IGMoMiwgMykpCgplZGYKYGBgCgpUaGUgYGZyb21gIGFuZCBgdG9gIGFyZ3VtZW50cyBzcGVjaWZ5IHdoaWNoIG5vZGVzIHRoZSB0aGUgZWRnZSBpcyBvdXRnb2luZyBhbmQgaW5jb21pbmcsIHJlc3BlY3RpdmVseS4gSGVyZSwgdGhlIGVkZ2VzIGFyZTogIjEiIC0+ICIyIiBhbmQgIjEiIC0+ICIzIi4gRm9yIGRpcmVjdGVkIGdyYXBocywgdGhlIG9yZGVyIGlzIGVzc2VudGlhbC4gVGhlIGByZWxgIGFyZ3VtZW50IGFsbG93cyBmb3IgaW5jbHVzaW9uIG9mIHRleHQgbGFiZWxzIGluIHRoZSBzYW1lIG1hbm5lciBhcyB0aGUgbm9kZSBgdHlwZWAuIFRoaXMgaXMgdXNlZnVsIGZvciB0YXJnZXRpbmcgc3BlY2lmaWMgZ3JvdXBzIG9mIGVkZ2VzIGR1cmluZyBhIHNlbGVjdGlvbiBvciB0cmF2ZXJzYWwuIExldCdzIHJlZmluZSB0aGUgYGVkZmAgb2JqZWN0IGFuZCBpbmNsdWRlIHR3byBkaWZmZXJlbnQgYHJlbGAgdmFsdWVzLgoKYGBge3J9CmVkZiA8LSAKICBjcmVhdGVfZWRnZV9kZigKICAgIGZyb20gPSBjKDEsIDEpLAogICAgdG8gICA9IGMoMiwgMyksCiAgICByZWwgPSBjKCJYIiwgIlkiKSkKCmVkZgpgYGAKCk5vdyB0aGF0IHdlIGhhdmUgYW4gbmRmIGFuZCBhbiBlZGYsIHdlIGNhbiBub3cgY29tYmluZSB0aG9zZSBpbnRvIGEgZ3JhcGggb2JqZWN0LgoKYGBge3J9CnRoZV9ncmFwaCA8LSAKICBjcmVhdGVfZ3JhcGgoCiAgICBub2Rlc19kZiA9IG5kZiwKICAgIGVkZ2VzX2RmID0gZWRmKQpgYGAKCkhhdmluZyBhIGdyYXBoIG9iamVjdCBpcyBhIGdyZWF0IGZpcnN0IHN0ZXAgYW5kIHlvdSBjYW4gZG8gYSBsb3Qgd2l0aCB0aGVtIChpbnNwZWN0LCBtb2RpZnksIGpvaW4gd2l0aCBvdGhlciBncmFwaCBvYmplY3RzLCBldGMuKS4gV2hlbmV2ZXIgeW91J2QgbGlrZSB0byB2aWV3IHRoZSBncmFwaCwgdXNlIHRoZSBgcmVuZGVyX2dyYXBoKClgIGZ1bmN0aW9uLiBUaGVyZSBhcmUgdGhyZWUgcmVuZGVyZXJzIGZvciBncmFwaHM6CgojIyMgR3JhcGh2aXoKCmBgYHtyfQpyZW5kZXJfZ3JhcGgoZ3JhcGggPSB0aGVfZ3JhcGgsIG91dHB1dCA9ICJncmFwaCIpCmBgYAoKIyMjIFZpdmFncmFwaApgYGB7cn0KcmVuZGVyX2dyYXBoKGdyYXBoID0gdGhlX2dyYXBoLCBvdXRwdXQgPSAidml2YWdyYXBoIikKYGBgCgojIyMgdmlzTmV0d29yawpgYGB7cn0KcmVuZGVyX2dyYXBoKGdyYXBoID0gdGhlX2dyYXBoLCBvdXRwdXQgPSAidmlzTmV0d29yayIpCmBgYAoKIyMgUGFydCAyLiBBIFNob3J0Y3V0IHRvIHRoZSBTYW1lIEdyYXBoCgpZb3UgZG9uJ3QgcmVhbGx5IG5lZWQgdG8gaGF2ZSBhIG5vZGUgZGF0YSBmcmFtZSBpbiBjb25qdW5jdGlvbiB3aXRoIHRoZSBlZGdlIGRhdGEgZnJhbWUgdG8gbWFrZSBhIGdyYXBoIG9iamVjdC4gWW91IGNhbiBoYXZlIGJvdGgsIGVpdGhlciBvZiB0aGVtLCBvciBuZWl0aGVyIG9mIHRoZW0gKGNyZWF0aW5nIGFuIGVtcHR5IGdyYXBoKS4gSGVyZSBpcyB0aGUgZW1wdHkgZ3JhcGggY2FzZToKCmBgYHtyfQpyZW5kZXJfZ3JhcGgoY3JlYXRlX2dyYXBoKCkpCmBgYAoKSWYgeW91IHdhbnRlZCB0byBtYWtlIHRoZSBzYW1lIG5vbi1lbXB0eSBncmFwaCBhcyBiZWZvcmUsIGJ1dCB3aXRoIG9uZSBsZXNzIHN0ZXAsIGp1c3QgY3JlYXRlIHRoZSBlZGYgdGhlbiB1c2UgYGNyZWF0ZV9ncmFwaCgpYC4gVGhlIG5vZGVzIHdpbGwgaGF2ZSBtaW5pbWFsIG5vZGUgYXR0cmlidXRlcyBzZXQgKGkuZS4sIG5vIGB0eXBlYCB2YWx1ZXMgc2V0KS4KCmBgYHtyfQojIENyZWF0ZSB0aGUgZWRnZSBkYXRhIGZyYW1lCmVkZiA8LSAKICBjcmVhdGVfZWRnZV9kZigKICAgIGZyb20gPSBjKDEsIDEpLAogICAgdG8gICA9IGMoMiwgMykpCgojIFVzZSB0aGUgYGNyZWF0ZV9ncmFwaCgpYCBmdW5jdGlvbgp0aGVfZ3JhcGggPC0gY3JlYXRlX2dyYXBoKGVkZ2VzX2RmID0gZWRmKQoKIyBUaGUgZ3JhcGggc2hvdWxkIGJlIHNpbWlsYXIsIGJ1dCwgdGhlIG5vZGUgYHR5cGVgCiMgaGFzbid0IGJlZW4gc2V0IChzbyBubyBjb2xvcmluZyBvZiB0d28gZGlmZmVyZW50CiMgZ3JvdXBzIG9mIG5vZGVzKQpyZW5kZXJfZ3JhcGgoZ3JhcGggPSB0aGVfZ3JhcGgpCmBgYAoKIyMgUGFydCAzLiBHcmFwaCB3aXRoIE5vZGVzIGJ1dCBObyBFZGdlcwoKV2UgY2FuIGp1c3QgZGlzcGxheSBub2RlcyB3aXRob3V0IGVkZ2VzIGJ5IHBhc3NpbmcgaW4ganVzdCBhIG5vZGUgZGF0YSBmcmFtZSB0byB0aGUgYGNyZWF0ZV9ncmFwaCgpYCBmdW5jdGlvbi4KCmBgYHtyfQojIENyZWF0ZSB0aGUgbm9kZSBkYXRhIGZyYW1lCm5kZiA8LSAKICBjcmVhdGVfbm9kZV9kZigKICAgIG4gPSAzLAogICAgbGFiZWwgPSBjKCJBIiwgIkIiLCAiQyIpKQoKIyBVc2UgdGhlIGBjcmVhdGVfZ3JhcGgoKWAgZnVuY3Rpb24KdGhlX2dyYXBoIDwtIGNyZWF0ZV9ncmFwaChub2Rlc19kZiA9IG5kZikKCiMgVmlldyB0aGUgZ3JhcGgKcmVuZGVyX2dyYXBoKGdyYXBoID0gdGhlX2dyYXBoKQpgYGAKCkhlcmUgaXMgYW4gZXhhbXBsZSB3aXRoIDI2IG5vZGVzLCB0aGlzIHRpbWUgd3JhcHBpbmcgdGhlIGBjcmVhdGVfbm9kZXMoKWAsIGBjcmVhdGVfZ3JhcGgoKWAsIGFuZCBgcmVuZGVyX2dyYXBoKClgIGZ1bmN0aW9uIGNhbGxzIGludG8gb25lIGJpZyBzdGF0ZW1lbnQuCgpgYGB7cn0KcmVuZGVyX2dyYXBoKAogIGNyZWF0ZV9ncmFwaCgKICAgIG5vZGVzX2RmID0KICAgICAgY3JlYXRlX25vZGVfZGYoCiAgICAgICAgbiA9IDI2LAogICAgICAgIGxhYmVsID0gTEVUVEVSUykpKQpgYGAKClVuaWNvZGUgY2hhcmFjdGVycyBjYW4gYWxzbyBiZSB1c2VkIGFzIGBsYWJlbGAgYXR0cmlidXRlIHZhbHVlczoKCmBgYHtyfQpyZW5kZXJfZ3JhcGgoCiAgY3JlYXRlX2dyYXBoKAogICAgbm9kZXNfZGYgPQogICAgICBjcmVhdGVfbm9kZV9kZigKICAgICAgICBuID0gMywKICAgICAgICBsYWJlbCA9IGMoIs6xIiwgIs6yIiwgIs6zIikpKSkKYGBgCgpOZXN0aW5nIGNhbGxzIGxpa2UgYmVjb21lcyBsZXNzIHJlYWRhYmxlIHdpdGggaW5jcmVhc2luZyBudW1iZXJzIG9mIG9wZXJhdGlvbnMuICoqRGlhZ3JhbW1lUioqIHdvcmtzIHZlcnkgd2VsbCB3aXRoIHRoZSAqKm1hZ3JpdHRyKiogcGFja2FnZSB0byBhbGxvdyBmb3J3YXJkLXBpcGluZyBvZiBncmFwaCBvcGVyYXRpb25zIHdpdGggdGhlIGAlPiVgIG9wZXJhdG9yLiBIZXJlIGlzIHRoZSBzYW1lIHNldCBvZiBmdW5jdGlvbnMgYXMgYWJvdmUsIGV4Y2VwdCB1c2luZyBgJT4lYCB0byBjaGFpbiB0aGUgb3BlcmF0aW9ucyBsZWZ0IHRvIHJpZ2h0OgoKYGBge3J9CmNyZWF0ZV9ub2RlX2RmKAogIG4gPSAzLCBsYWJlbCA9IGMoIs6xIiwgIs6yIiwgIs6zIikpICU+JQogIGNyZWF0ZV9ncmFwaChub2Rlc19kZiA9IC4pICU+JQogIHJlbmRlcl9ncmFwaApgYGAKClRoZSBgLmAgY2hhcmFjdGVyIGluIHRoZSBgY3JlYXRlX2dyYXBoKClgIHN0YXRlbWVudCBpbmRpY2F0ZXMgdGhhdCB0aGUgcmV0dXJuZWQgb3V0cHV0IGZyb20gdGhlIHByZXZpb3VzIGBjcmVhdGVfbm9kZV9kZigpYCBzdGF0ZW1lbnQgc2hvdWxkIGdvIGhlcmUuIE90aGVyd2lzZSwgdGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgdGhhdCB0aGUgb3V0cHV0IGZyb20gYSBzdGF0ZW1lbnQgYmVjb21lcyB0aGUgdmFsdWUgZm9yIHRoZSBmaXJzdCBhcmd1bWVudCAod2hpY2ggaXMgb2Z0ZW4gb21pdHRlZCBlbnRpcmVseSkuIFRoZSBmdW5jdGlvbnMgaW4gKipEaWFncmFtbWVSKiogYXJlIGRlc2lnbmVkIHRvIGhhdmUgdGhpcyBmb3J3YXJkLXBpcGUgcGF0dGVybiB3b3JrIHdlbGwuIFdpdGggZnVydGhlciBleGFtcGxlcywgeW91J2xsIHNlZSBob3cgdGhpcyBjYW4gbWFrZSBldmVuIGNvbXBsaWNhdGVkIGdyYXBoIG9wZXJhdGlvbnMgZWFzeSB0byBjb21wb3NlIGFuZCB0byByZWFkLgoK